package com.example.music.download;

import java.io.*;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;

public class TEST {
    public static void main(String[] args) throws IOException, InterruptedException {
        long l = System.currentTimeMillis();
        URL url = new URL("https://v1.cecdn.yun300.cn/site_1807160375/邓记20周年最终播出版小格式.mp4（备播）1537074001195.mp4");
        //读的通道，拿到文件并放进通道
        ReadableByteChannel readableByteChannel = Channels.newChannel(url.openStream());

        //输出流
        FileOutputStream fileOutputStream = new FileOutputStream("D:\\2.mp4");

        //写的通道，通过transferFrom拷贝，将文件从readableByteChannel通道拷贝出去"D:\\2.mp4"
        fileOutputStream.getChannel().transferFrom(readableByteChannel, 0, Long.MAX_VALUE);
        fileOutputStream.close();
        readableByteChannel.close();


        System.out.println((System.currentTimeMillis() - l) / 1000 + "s");

    }


    public static void downloadMusic(String htmlurl, String path) throws IOException {

        URL url = new URL(htmlurl);
        //读的通道，拿到文件并放进通道
        ReadableByteChannel readableByteChannel = Channels.newChannel(url.openStream());

        //输出流
        FileOutputStream fileOutputStream = new FileOutputStream(path);

        //写的通道，通过transferFrom拷贝，将文件从readableByteChannel通道拷贝出去"D:\\2.mp4"
        fileOutputStream.getChannel().transferFrom(readableByteChannel, 0, Long.MAX_VALUE);
        fileOutputStream.close();
        readableByteChannel.close();

    }

    /**
     * @author yzh
     * @time 2023/4/4
     * <p>
     * buffer拷贝，通过buffer下载，和transferFrom速度一样
     */

    private static void channelCopy1(ReadableByteChannel src,
                                     WritableByteChannel dest) {
        // 分配一个新的直接字节缓冲区
        ByteBuffer buffer = ByteBuffer.allocateDirect(16 * 1024);
        try {
            while (src.read(buffer) != -1) {
                // 读转变成写模式
                buffer.flip();
                dest.write(buffer);
                buffer.compact();
            }
            // 确保缓冲区完全排干
            while (buffer.hasRemaining()) {
                dest.write(buffer);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*以下两个方法同一个文章中的*/

    /**
     * @author yzh
     * @time 2023/4/4
     * <p>
     * 调用transferFrom或transferTo，直接复制通道数据
     */
    public void transferFromORtransferTo() throws IOException {
        //=========== 创建读通道 ===========
        //拿到文件
        File file = new File("d:\\test\\write.txt");
        FileInputStream inputStream = new FileInputStream(file);
        //创建管道，把文件放入通道
        FileChannel fileChannel = inputStream.getChannel();


        //=========== 创建写通道 ===========
        //创建文件
        FileOutputStream outputStream = new FileOutputStream("d:\\test\\write22.txt");
        //创建Channel2，把文件放入通道
        FileChannel fileChannel2 = outputStream.getChannel();

        //=========== transferFrom从目标通道复制到当前通道 ===========
        fileChannel2.transferFrom(fileChannel, 0, fileChannel.size());

        //=========== 关闭与清除 ===========
        fileChannel2.close();
        outputStream.close();
        fileChannel.close();
        inputStream.close();

    }

    /**
     * @author yzh
     * @time 2023/4/4
     * 从Buffer中拷贝
     */
    public static void buffer() throws Exception {
        //=========== 读 ===========
        //拿到文件
        File file = new File("d:\\test\\write.txt");
        FileInputStream inputStream = new FileInputStream(file);
        //创建管道，把文件放入通道
        FileChannel fileChannel = inputStream.getChannel();
        //创建Buffer
        ByteBuffer buffer = ByteBuffer.allocate((int) file.length());
        //从通道读数据放入缓冲区
        fileChannel.read(buffer);

        //=========== 反转读写模式 ===========
        buffer.flip();

        //=========== 写 ===========
        //创建文件
        FileOutputStream outputStream = new FileOutputStream("d:\\test\\write2.txt");
        //创建Channel2，把文件放入通道
        FileChannel fileChannel2 = outputStream.getChannel();
        //把Buffer内容放入Channel2
        fileChannel2.write(buffer);

        //=========== 关闭与清除 ===========
        fileChannel2.close();
        outputStream.close();
        fileChannel.close();
        inputStream.close();
        buffer.clear();
    }
    /*完*/

}
